package view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Scroller;

public class SlidingFrame extends ViewGroup {
    final private int STATE_CENTRE_IDLE = 3;
    final private int STATE_CENTRE_TO_LEFT = 4;
    final private int STATE_CENTRE_TO_RIGHT = 6;
    final private int STATE_LEFT_IDLE = 1;
    final private int STATE_LEFT_TO_CENTRE = 5;
    final private int STATE_RIGHT_IDLE = 2;
    final private int STATE_RIGHT_TO_CENTRE = 7;
    protected int leftWidthPercentage = 60;
    protected FrameLayout leftContiner;
    protected FrameLayout centreContiner;
    /**
     * 中间View左上角的X坐标
     */
    protected int position = 0;
    private int animationDuration = 400;
    private boolean blockTouchEvent;
    private View centreView;
    private float firstX, firstY;
    /**
     * 是否设置了左侧的View
     */
    private boolean hasLeftView;
    /**
     * 是否设置了右侧的View
     */
    private boolean hasRightView;
    /**
     * 是否拦截触屏事件
     */
    private boolean interceptFlag;
    /**
     * 当前中间View滑动的位置
     */
    private int lastPosition;
    /**
     * 用于显示左侧的阴影
     */
    private View leftShadow;
    private int leftShadowWidth;
    private View leftView;
    /**
     * 左边View的宽度
     */
    private int leftWidth;
    private SlidingStateListener listener;
    private FrameLayout rightContiner;
    private View rightShadow;
    private int rightShadowWidth;
    private View rightView;
    /**
     * 右边View的宽度
     */
    private int rightWidth;
    private int rightWidthPercentage = 60;
    private Scroller scroller;
    private boolean slideFromEdge = true;
    private int slidingState = STATE_CENTRE_IDLE;
    private boolean startFromEdge;
    private ViewConfiguration viewConfiguration;

    public SlidingFrame(Context context) {
        super(context);
        init(context);
    }

    private void init(Context c) {
        leftShadow = new View(c);
        rightShadow = new View(c);
        leftContiner = new FrameLayout(c);
        rightContiner = new FrameLayout(c);
        centreContiner = new FrameLayout(c) {
            public boolean onInterceptTouchEvent(MotionEvent ev) {
                if (blockTouchEvent) {
                    return true;
                }
                return super.onInterceptTouchEvent(ev);
            }

            ;
        };
        centreContiner.setBackgroundColor(Color.WHITE);
        //		leftContiner.setId(View.generateViewId());
        //		rightContiner.setId(View.generateViewId());
        //		centreContiner.setId(View.generateViewId());
        setBackgroundColor(Color.BLACK);
        addAllViews();
        scroller = new Scroller(c);
        viewConfiguration = ViewConfiguration.get(c);
    }

    private void addAllViews() {
        addView(leftContiner);
        addView(rightContiner);
        addView(leftShadow);
        addView(rightShadow);
        addView(centreContiner);
    }

    public SlidingFrame(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public FrameLayout getCenterContiner() {
        // TODO Auto-generated method stub
        return centreContiner;
    }

    public boolean isLeftMenuOpened() {
        return position > 0;
    }    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (slidingState == STATE_CENTRE_TO_LEFT || slidingState == STATE_LEFT_IDLE || slidingState == STATE_LEFT_TO_CENTRE) {
            if (ev.getX() < position + getMeasuredWidth()) {
                blockTouchEvent = true;
            }
        } else if (slidingState == STATE_CENTRE_TO_RIGHT || slidingState == STATE_RIGHT_TO_CENTRE || slidingState == STATE_RIGHT_IDLE) {
            if (ev.getX() > position) {
                blockTouchEvent = true;
            }
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                firstX = ev.getX();
                firstY = ev.getY();
                lastPosition = position;
                interceptFlag = false;
                if (firstX > viewConfiguration.getScaledEdgeSlop() + getLeft() && firstX + viewConfiguration.getScaledEdgeSlop() < getRight()) {
                    startFromEdge = false;
                } else {
                    startFromEdge = true;
                }
                startFromEdge |= !slideFromEdge;
                break;
            case MotionEvent.ACTION_MOVE:
                if (!interceptFlag) {
                    float dx = ev.getX() - firstX;
                    float dy = ev.getY() - firstY;
                    if (startFromEdge && Math.abs(dx) + Math.abs(dy) > viewConfiguration.getScaledTouchSlop() && Math.abs(dx) > Math.abs(dy)) {
                        interceptFlag = true;
                    }
                }
        }
        return interceptFlag;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //		System.out.println("SlidingFrame onTouchEvent()");
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
                smoothScroll();
                return false;
            case MotionEvent.ACTION_DOWN://onInterceptTouchEvent 返回true跳到这里
                if (!scroller.isFinished()) {
                    scroller.forceFinished(true);
                }
                firstX = ev.getX();
                return true;
            case MotionEvent.ACTION_MOVE:
                if (!scroller.isFinished()) {
                    scroller.forceFinished(true);
                }
                float distanceX = ev.getX() - firstX;
                float dx = position - lastPosition - distanceX;
                if (dx < 1 & dx > -1) {
                    return false;
                }
                //			System.out.println("position="+position);
                if (slidingState == STATE_LEFT_IDLE && dx > 0) {
                    return true;
                } else if (slidingState == STATE_RIGHT_IDLE && dx < 0) {
                    return true;
                }
                position = (int) (lastPosition + distanceX);//dx>0 往左滑动
                if (position > leftWidth) {
                    position = leftWidth;
                } else if (position < -rightWidth) {
                    position = -rightWidth;
                }
                if (position > 0) {
                    if (dx > 0) {
                        slidingState = STATE_RIGHT_TO_CENTRE;
                    } else {
                        slidingState = STATE_CENTRE_TO_RIGHT;
                    }
                } else if (position < 0) {
                    if (dx > 0) {
                        slidingState = STATE_CENTRE_TO_LEFT;
                    } else {
                        slidingState = STATE_LEFT_TO_CENTRE;
                    }
                }
                layoutChildren();
                postInvalidate();
                return true;
        }
        return false;
    }    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        layoutChildren();
    }

    @Override
    public void computeScroll() {
        int interval = 5;
        if (scroller.computeScrollOffset()) {
            position = scroller.getCurrX();
            if (position >= leftWidth + interval) {
                position = leftWidth;
                scrollTo(position, 0);
                scroller.forceFinished(true);
                slidingState = STATE_RIGHT_IDLE;
                if (null != listener) {
                    listener.toTheRight();
                }
            } else if (position <= -rightWidth - interval) {
                scroller.forceFinished(true);
                position = -rightWidth;
                scrollTo(position, 0);
                slidingState = STATE_LEFT_IDLE;
                if (null != listener) {
                    listener.toTheLeft();
                }
            } else if (position < interval && position > -interval) {
                scroller.forceFinished(true);
                position = 0;
                scrollTo(position, 0);
                slidingState = STATE_CENTRE_IDLE;
                blockTouchEvent = false;
                if (null != listener) {
                    listener.toTheCentre();
                }
            }
            layoutChildren();
            postInvalidate();//不调用可能看不到滚动效果，不要换成invalidate()
        } else {
            if (position == 0) {
                blockTouchEvent = false;
                slidingState = STATE_CENTRE_IDLE;
            }
        }
    }

    @SuppressLint("NewApi")
    protected void layoutChildren() {
        boolean canAlpha = android.os.Build.VERSION.SDK_INT > 10;
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();

        if (position < 0) {
            leftContiner.setVisibility(View.INVISIBLE);
            leftShadow.setVisibility(View.INVISIBLE);
            rightContiner.setVisibility(View.VISIBLE);
            rightShadow.setVisibility(View.VISIBLE);
            int left = width + position / 2 - rightWidth / 2;
            int top = height / 4 + height * position / rightWidth / 4;
            rightContiner.layout(left, top, left + rightWidth, top + height);
            if (rightShadowWidth != 0) {
                rightShadow.layout(position + width, 0, position + rightShadowWidth + width, height);
            }
            if (canAlpha) {
                rightContiner.setAlpha((-position * 0.9f) / rightWidth + 0.1f);
            }
        } else if (position > 0) {
            rightContiner.setVisibility(View.INVISIBLE);
            rightShadow.setVisibility(View.INVISIBLE);
            leftContiner.setVisibility(View.VISIBLE);
            leftShadow.setVisibility(View.VISIBLE);
            int left = -leftWidth / 2 + position / 2;
            int top = height / 4 - height * position / leftWidth / 4;
            leftContiner.layout(left, top, left + leftWidth, top + height);
            if (leftShadowWidth != 0) {
                leftShadow.layout(position - leftShadowWidth, 0, position, height);
            }
            if (canAlpha) {
                leftContiner.setAlpha(position * 0.9f / leftWidth + 0.1f);
            }
        } else {
            leftContiner.setVisibility(View.INVISIBLE);
            leftShadow.setVisibility(View.INVISIBLE);
            rightContiner.setVisibility(View.INVISIBLE);
            rightShadow.setVisibility(View.INVISIBLE);

        }
        centreContiner.layout(position, 0, width + position, height);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        centreContiner.measure(widthMeasureSpec, heightMeasureSpec);
        if (hasLeftView) {
            measureMyChild(leftContiner, width, height, leftWidthPercentage);
            leftWidth = leftContiner.getMeasuredWidth();
        }
        if (hasRightView) {
            measureMyChild(rightContiner, width, height, rightWidthPercentage);
            rightWidth = rightContiner.getMeasuredWidth();
        }
        setMeasuredDimension(width, height);
    }

    private void measureMyChild(FrameLayout childView, int width, int height, int percentage) {
        int childWidthMeasureSpec = 0;
        LayoutParams params = childView.getChildAt(0).getLayoutParams();
        if (params.width == LayoutParams.WRAP_CONTENT) {
            childWidthMeasureSpec = getChildMeasureSpec(MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED), 0, LayoutParams.WRAP_CONTENT);
        } else if (params.width == LayoutParams.MATCH_PARENT) {
            childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width * percentage / 100, MeasureSpec.EXACTLY);
        } else {
            childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(params.width, MeasureSpec.EXACTLY);
        }
        int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        childView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        //		childView.getLayoutParams().width = params.width;
        //		childView.getLayoutParams().height = params.height;
        //		measureChild(childView, childWidthMeasureSpec, childHeightMeasureSpec);
    }

    private void smoothScroll() {
        switch (slidingState) {
            case STATE_CENTRE_TO_RIGHT:
                scroller.startScroll(position, 0, leftWidth - position, 0, animationDuration);
                break;
            case STATE_RIGHT_TO_CENTRE:
                scroller.startScroll(position, 0, -position, 0, animationDuration);
                break;
            case STATE_LEFT_TO_CENTRE:
                scroller.startScroll(position, 0, -position, 0, animationDuration);
                break;
            case STATE_CENTRE_TO_LEFT:
                scroller.startScroll(position, 0, -rightWidth - position, 0, animationDuration);
                break;
        }
        postInvalidate();//不调用看不到滚动效果
    }

    /**
     * 设置动画持续时间，单位毫秒
     */
    public void setAnimationDuration(int duration) {
        animationDuration = duration;
    }

    /**
     * 设置中间的View
     */
    public void setCentreView(View v) {
        centreView = v;
        centreContiner.addView(centreView);
    }

    /**
     * 设置左侧阴影
     *
     * @param resid 背景资源ID
     * @param width 阴影宽度，单位像素
     */
    public void setLeftShadow(int resid, int width) {
        leftShadow.setBackgroundResource(resid);
        leftShadowWidth = width;
    }

    /**
     * 设置左侧的View
     */
    public void setLeftView(View v) {
        hasLeftView = true;
        leftView = v;
        leftContiner.addView(leftView);
    }

    /**
     * 当left的LayoutParams的宽度为MathParent时设置此参数有效
     *
     * @param percentage 1~100,不调用此方法则根据View的LayoutParams来设置，如果没有设置LayoutParams则高度MatchParent，宽度WrapContent
     */
    public void setLeftWidth(int percentage) {
        leftWidthPercentage = percentage;
        if (leftWidthPercentage > 100 || leftWidthPercentage < 0) {
            throw new IllegalAccessError("percentage 范围 1~100");
        }
    }

    /**
     * 设置右侧阴影
     *
     * @param resid 背景资源ID
     * @param width 阴影宽度，单位像素
     */
    public void setRightShadow(int resid, int width) {
        rightShadow.setBackgroundResource(resid);
        rightShadowWidth = width;
    }

    /**
     * 设置右侧的View
     */
    public void setRightView(View v) {
        hasRightView = true;
        rightView = v;
        rightContiner.addView(rightView);
    }

    /**
     * 当left的LayoutParams的宽度为MathParent时设置此参数有效
     *
     * @param percentage 1~100,不调用此方法则根据View的LayoutParams来设置，如果没有设置LayoutParams则高度MatchParent，宽度WrapContent
     */
    public void setRightWidth(int percentage) {
        rightWidthPercentage = percentage;
        if (rightWidthPercentage > 100 || rightWidthPercentage < 1) {
            throw new IllegalAccessError("percentage 范围 1~100");
        }
    }

    /**
     * 是否从边缘滑动才触发侧滑
     *
     * @param slideFromEdge
     */
    public void setSlideFromEdge(boolean slideFromEdge) {
        this.slideFromEdge = slideFromEdge;
    }

    /**
     * @param listener 当滑动停止时的回调，左侧停下，右侧停下，中间停下
     */
    public void setSlidingStateListener(SlidingStateListener listener) {
        this.listener = listener;
    }

    /**
     * 如果不在中间则滑动到中间
     */
    public void slideToCentre() {
        if (position > 0) {
            scroller.forceFinished(true);
            slidingState = STATE_RIGHT_TO_CENTRE;
            smoothScroll();
        } else if (position < 0) {
            scroller.forceFinished(true);
            slidingState = STATE_LEFT_TO_CENTRE;
            smoothScroll();
        }
    }

    /**
     * 在中间状态时，调用此函数会滑动到左侧。
     */
    public void slideToLeft() {
        if (hasRightView && slidingState == STATE_CENTRE_IDLE) {
            scroller.forceFinished(true);
            slidingState = STATE_CENTRE_TO_LEFT;
            smoothScroll();
        }
    }

    /**
     * 在中间状态时，调用此函数会滑动到右侧。
     */
    public void slideToRight() {
        if (hasLeftView && slidingState == STATE_CENTRE_IDLE) {
            scroller.forceFinished(true);
            slidingState = STATE_CENTRE_TO_RIGHT;
            smoothScroll();
        }
    }

    /**
     * 当滑动停止时的回调，左侧停下，右侧停下，中间停下
     */
    public interface SlidingStateListener {
        /**
         * 滑动到中间停下
         */
        void toTheCentre();

        /**
         * 滑动到左侧停下
         */
        void toTheLeft();

        /**
         * 滑动到右侧停下
         */
        void toTheRight();
    }





}
